package validator;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.JsonNodeType;
import com.networknt.schema.AbstractJsonValidator;
import com.networknt.schema.AbstractKeyword;
import com.networknt.schema.CustomErrorMessageType;
import com.networknt.schema.JsonSchema;
import com.networknt.schema.JsonValidator;
import com.networknt.schema.ValidationContext;
import com.networknt.schema.ValidationMessage;

import java.nio.charset.StandardCharsets;
import java.text.MessageFormat;
import java.util.Set;

/**
 * Example validator for the "maxUtf8ByteLength" keyword.
 */
public class MaxUtf8ByteLengthKeyword  extends AbstractKeyword {

    private static final MessageFormat ERROR_MESSAGE_FORMAT =
            new MessageFormat("Value must be less than or equal {1} bytes in length.");

    private static final String KEYWORD = "maxUtf8ByteLength";

    public MaxUtf8ByteLengthKeyword() {
        super(KEYWORD);
    }

    @Override
    public JsonValidator newValidator(String schemaPath, JsonNode schemaNode, JsonSchema parentSchema,
                                      ValidationContext validationContext) {

        // Only process if the provided schema value is a number.
        if (!JsonNodeType.NUMBER.equals(schemaNode.getNodeType())) {
            return null;
        }

        int maxUtf8ByteLength = schemaNode.asInt();

        return new AbstractJsonValidator(this.getValue()) {

            @Override
            public Set<ValidationMessage> validate(JsonNode node, JsonNode rootNode, String at) {

                // Get the value as a string and evaluate its length in bytes.
                String value = node.asText();
                if (value.getBytes(StandardCharsets.UTF_8).length > maxUtf8ByteLength) {
                    return fail(CustomErrorMessageType.of(KEYWORD, ERROR_MESSAGE_FORMAT), at,
                            Integer.toString(maxUtf8ByteLength));
                }
                return pass();
            }
        };
    }
}
